package com.smartsaas.ugclivii.utils;

import com.smartsaas.ugclivii.ui.UiContext;
import nxopen.*;
import nxopen.blockstyler.Node;
import nxopen.blockstyler.SpecifyCSYS;
import nxopen.blockstyler.Tree;
import nxopen.uf.*;

import java.io.File;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class FunUtils {
    /**
     * 获得点云
     */
    public static List<double[]> getPts(Face[] faces, int uv) throws RemoteException, NXException {
        UFEvalsf evalsf = UiContext.UF_SESSION.evalsf();
        List<double[]> res = new ArrayList<>();
        for (Face face : faces) {
            double[] uvPair={0,0};
            UFVariant evaluator = evalsf.initialize(face.tag());
            double[] uvBox = evalsf.askFaceUvMinmax(evaluator);
            for (int i = 0; i < uv; i++) {
                uvPair[0]=uvBox[0]+(i+1)*(uvBox[1]-uvBox[2])/(uv+1);
                for (int j = 0; j < uv; j++) {
                    uvPair[1]=uvBox[2]+(j+1)*(uvBox[3]-uvBox[2])/(uv+1);
                    // #define UF_MODL_EVAL   0
                    UFModl.Srfvalue evaluate = evalsf.evaluate(evaluator, 0, uvPair);
                    res.add(evaluate.srfPos);
                }
            }
        }
        return res;
    }

    /**
     * 计算中心点
     */
    public static double[] getCenterPt(List<double[]> pts){
        double[] res={0,0,0};
        for (double[] pt : pts) {
            res[0]+=pt[0];
            res[1]+=pt[1];
            res[2]+=pt[2];
        }
        int nPts = pts.size();
        res[0]/= nPts;
        res[1]/= nPts;
        res[2]/= nPts;
        return res;
    }
    //获取体的盒子坐标
    public static double[] getBodyDistances(SpecifyCSYS csy, Body body) throws RemoteException, NXException {
        if (body.isSolidBody()){
            if (csy!=null){
                TaggedObject[] tags = csy.getSelectedObjects();
                if (tags!=null){
                    TaggedObject tag = tags[0];
                    UFModlGeneral modl = UiContext.UF_SESSION.modlGeneral();
                    UFModlGeneral.AskBoundingBoxExactData boxExactData = modl.askBoundingBoxExact(body.tag(), tag.tag());
                    return boxExactData.distances;
                }
            }
        }
        return null;
    }
    public static double[] getBodyDistances(Tag csy, Body body) throws RemoteException, NXException {
        if (body.isSolidBody()){
            if (csy!=null){
                UFModlGeneral modl = UiContext.UF_SESSION.modlGeneral();
                UFModlGeneral.AskBoundingBoxExactData boxExactData = modl.askBoundingBoxExact(body.tag(), csy);
                return boxExactData.distances;
            }
        }
        return null;
    }
    //计算点云到中心点的距离
    public static Set<Integer> getPtsToCenterPtDists(double[] centerPt, List<double[]> pts) throws RemoteException, NXException {
        UFVec3 vec3 = UiContext.UF_SESSION.vec3();
        Set<Integer> res=new HashSet<>();
        for (double[] pt : pts) {
            double distance = vec3.distance(pt, centerPt);
            res.add((int) distance*10);
        }
        return res;
    }

    public static Set<Integer> getBodyPtstoCenterPtDists(Body body) throws NXException, RemoteException {
        List<double[]> pts = getPts(body.getFaces(), 3);
        double[] centerPt = getCenterPt(pts);
        return getPtsToCenterPtDists(centerPt, pts);
    }

    public static boolean solidBodyEq(Body target,Body body) throws RemoteException, NXException {
        if (body.isSheetBody()){
            return false;
        }
        int faceLength = body.getFaces().length;
        int edgeLength = body.getEdges().length;
        if (target.getFaces().length!=faceLength||target.getEdges().length!=edgeLength){
            return false;
        }
        Set<Integer> targetDists = getBodyPtstoCenterPtDists(target);
        Set<Integer> bodyDists = getBodyPtstoCenterPtDists(body);
        return targetDists.equals(bodyDists);
    }

    public static List<Body> findSameBody(Body target, TaggedObject[] bodies) throws NXException, RemoteException {
        List<Body> selected=new ArrayList<>();
        if (target.isSolidBody()){
            for (TaggedObject tag : bodies) {
                Body body = (Body) tag;
                if (!target.equals(body)){
                    if (solidBodyEq(target,body)){
                        selected.add(body);
                    }
                }
            }
        }
        return selected;
    }

    public static void clearTree(Tree tree) throws NXException, RemoteException {
        Node root = tree.rootNode();
        if (root==null){
            return;
        }
        ArrayList<Node> nodes = new ArrayList<>();
        getAllNode(root, nodes);
        for (Node node : nodes) {
            tree.deleteNode(node);
        }
    }

    public static void getAllNode(Node root,List<Node> res) throws NXException, RemoteException {
        res.add(root);
        Node next = root.nextNode();
        if (next!=null){
            getAllNode(next,res);
        }
    }

    public static int cylindricalFaceRedius(Face face) throws RemoteException, NXException {
        UFModeling modeling = UiContext.UF_SESSION.modeling();
        UFModeling.AskFaceData askFaceData = modeling.askFaceData(face.tag());
        return (int) askFaceData.radius;
    }

    public static int cylindricalDict(Face face) throws NXException, RemoteException {
        Edge[] edges = face.getEdges();
        Part work = UiContext.SESSION.parts().work();
        List<Point3d> point3ds=new ArrayList<>();
        for (Edge edge : edges) {
            if (!isEdgeClose(edge)){
                continue;
            }
            Section section = work.sections().createSection(edge);
            Arc curve =(Arc) work.curves().createSmartCompositeCurve(section, SmartObject.UpdateOption.WITHIN_MODELING, 0.001);
            point3ds.add(curve.centerPoint());
        }
        double a = Math.pow(point3ds.get(0).x - point3ds.get(1).x, 2) + Math.pow(point3ds.get(0).y - point3ds.get(1).y, 2) + Math.pow(point3ds.get(0).z - point3ds.get(1).z, 2);
        double dis = Math.sqrt(a);
        return (int) dis;
    }

    public static boolean isEdgeClose(Edge edge) throws NXException, RemoteException {
        Edge.VerticesData vertices = edge.getVertices();
        Point3d vertex1 = vertices.vertex1;
        Point3d vertex2 = vertices.vertex2;
        return vertex1.x==vertex2.x&&vertex1.y==vertex2.y;
    }

    public static String mkdirForBizPath(String rootPath, String dirName) {
        File file = new File(rootPath, dirName);
        if (!file.exists()){
            file.mkdirs();
        }
        return file.getAbsolutePath();
    }

    public static void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteFolder(file);
                } else {
                    file.delete();
                }
            }
        }
        folder.delete();
    }


}
